﻿using System;
using System.Collections.Generic;
using System.Text;
using ActiproSoftware.SyntaxEditor;
using ActiproSoftware.SyntaxEditor.Addons.DotNet.Ast;

namespace WindowsUserControl.Codes
{
    /// <summary>
    /// Provides the base class for an AST node visitor.
    /// </summary>
    /// <remarks>
    /// <para>
    /// This class supports the visitor pattern.
    /// </para>
    /// <para>
    /// Each visitor implements a <c>OnVisiting</c> and an <c>OnVisited</c> method for each AST node type.
    /// By default the <c>OnVisiting</c> method returns <c>true</c>, while the <c>OnVisited</c> method does nothing.
    /// </para>
    /// <para>
    /// The <c>OnVisiting</c> method should return <c>true</c> if its child nodes should be visited.
    /// If <c>true</c> is returned, the child nodes are visiting in order.
    /// After the child nodes are visited, the <c>OnVisited</c> method is called.
    /// If <c>OnVisiting</c> returns <c>false</c>, child node visits are not made and <c>OnVisited</c> is called directly.
    /// </para>
    /// <para>
    /// Additionally, the generic <see cref="AstVisitor.OnPreVisiting"/> method is called before any type-specific <c>OnVisiting</c> method is executed
    /// and the generic <see cref="AstVisitor.OnPostVisited"/> method is called after any type-specific <c>OnVisited</c> method is executed.
    /// </para>
    /// </remarks>
    public abstract class AstVisitor
    {

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // GENERIC VISIT PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Visits the <see cref="IAstNode"/> after the type-specific <c>OnVisited</c> method is executed.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnPostVisited(AstNode node) { }

        /// <summary>
        /// Visits the <see cref="IAstNode"/> before the type-specific <c>OnVisiting</c> method is executed.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node and its children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnPreVisiting(AstNode node)
        {
            return true;
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // VISITING PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(AssignmentStatement node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(BinaryExpression node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(BlockStatement node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(CompilationUnit node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(EmptyStatement node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(FunctionAccessExpression node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(FunctionDeclaration node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(Identifier node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(NumberExpression node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(ParenthesizedExpression node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(ReturnStatement node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(SimpleName node)
        {
            return true;
        }

        /// <summary>
        /// Visits the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <returns>
        /// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
        /// </returns>
        public virtual bool OnVisiting(VariableDeclarationStatement node)
        {
            return true;
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // VISITED PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(AssignmentStatement node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(BinaryExpression node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(BlockStatement node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(CompilationUnit node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(EmptyStatement node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(FunctionAccessExpression node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(FunctionDeclaration node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(Identifier node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(NumberExpression node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(ParenthesizedExpression node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(ReturnStatement node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(SimpleName node) { }

        /// <summary>
        /// Ends the visit of the specified type of <see cref="IAstNode"/>.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual void OnVisited(VariableDeclarationStatement node) { }

    }
}
